
/**
 @file sys_usw_dma_priv.h

 @date 2012-11-30

 @version v2.0

*/
#ifndef _SYS_USW_DMA_PRIV_H
#define _SYS_USW_DMA_PRIV_H
#ifdef __cplusplus
extern "C" {
#endif

/***************************************************************
 *
 * Header Files
 *
 ***************************************************************/
#include "ctc_hash.h"
#include "ctc_debug.h"
#include "ctc_const.h"
#include "ctc_vector.h"
#include "sal_fifo.h"
/***************************************************************
 *
 *  Defines and Macros
 *
 ***************************************************************/
#define SYS_DMA_INIT_COUNT          4000
#define SYS_DMA_WORD_LEN            4
#define SYS_DMA_RING_SELECT_PRIROITY 10
/*channel crc length 0 or 4(only tsingma.mx)*/
#define SYS_USW_DMA_PKT_TX_CRC_LEN (p_dma_chan->tx_crc_len)
/*dma memory align size*/
#define SYS_DMA_ALIGN_SIZE 256
#define DATA_SIZE_ALIGN(size)     ((((uintptr)(size)) + (SYS_DMA_ALIGN_SIZE) - 1) & ~((SYS_DMA_ALIGN_SIZE) - 1))
/*dma debug and dump marco */
#define SYS_DMA_DBG_OUT(level, FMT, ...) \
    do { \
        CTC_DEBUG_OUT(dma, dma, DMA_SYS, level, FMT, ##__VA_ARGS__); \
    } while (0)

#define SYS_DMA_DUMP(FMT, ...)                  \
    do                                          \
    {                                           \
        CTC_DEBUG_OUT(dma, dma, DMA_SYS, CTC_DEBUG_LEVEL_DUMP, FMT, ## __VA_ARGS__); \
    } while (0)

#ifdef DMA_DBG_ON
#define SYS_DMA_CB_IN_CNT_ADD(lchip, chan) p_usw_dma_master[lchip]->dma_cb_in_cnt[chan]++
#define SYS_DMA_CB_OUT_CNT_ADD(lchip, chan) p_usw_dma_master[lchip]->dma_cb_out_cnt[chan]++
#else
#define SYS_DMA_CB_IN_CNT_ADD(lchip, chan)
#define SYS_DMA_CB_OUT_CNT_ADD(lchip, chan)
#endif

#if defined(CTC_ARCH_ARM64) && (SDB_MEM_MODEL != SDB_MODE)
#define DMA_SOC_MB()	asm volatile("dmb ish" ::: "memory")
#define DMA_SOC_RMB()	asm volatile("dmb ishld" ::: "memory")
#define DMA_SOC_WMB()	asm volatile("dmb ishst" ::: "memory")
#else
#define DMA_SOC_MB()
#define DMA_SOC_RMB()
#define DMA_SOC_WMB()
#endif

#ifndef PACKET_TX_USE_SPINLOCK
#define DMA_TX_LOCK(mutex) \
    if (mutex) sal_mutex_lock(mutex)
#define DMA_TX_UNLOCK(mutex) \
    if (mutex) sal_mutex_unlock(mutex)
#else
#define DMA_TX_LOCK(mutex) \
    if (mutex) sal_spinlock_lock((sal_spinlock_t*)mutex)
#define DMA_TX_UNLOCK(mutex) \
    if (mutex) sal_spinlock_unlock((sal_spinlock_t*)mutex)
#endif

#define DMA_LOCK(mutex) \
    if (mutex) sal_mutex_lock(mutex)
#define DMA_UNLOCK(mutex) \
    if (mutex) sal_mutex_unlock(mutex)

#define SYS_DMA_PKT_LEN_CHECK(len) \
    do { \
        if ((len) < 12 || (len) > (16127)) \
        { \
            return CTC_E_INVALID_PARAM; \
        } \
    } while (0)

struct sys_dma_stats_s
{
    union
    {
        uint64 total_pkt_cnt;    /*only D2 used*/
        uint64 good_pkt_cnt;
    }u1;
    union
    {
        uint64 total_byte_cnt;   /*only D2 used*/
        uint64 good_byte_cnt;
    }u2;
    union
    {
        uint64 drop_cnt;         /*only D2 used*/
        uint64 bad_pkt_cnt;
    }u3;
    union
    {
        uint64 error_cnt;        /*only D2 used*/
        uint64 bad_byte_cnt;
    }u4;
};
typedef struct sys_dma_stats_s sys_dma_stats_t;

struct sys_dma_tx_mem_s
{
    ctc_pkt_callback callback;
    void*           user_data;
    void*       p_pkt_addr;
    void* p_mem_addr;
};
typedef struct sys_dma_tx_mem_s sys_dma_tx_mem_t;

struct sys_dma_tx_check_s
{
    uint32 phy_address;
    uint32 pool_id    :16;
    uint32 is_used   :1;
    uint32 rsv       :15;
};
typedef struct sys_dma_tx_check_s sys_dma_tx_check_t;
struct sys_dma_chan_s
{
    uint32 chan_en          : 1;
    uint32 sync_chan        : 8;
    uint32 sync_en          : 1;
    uint32 pkt_knet_en      : 1;
    uint32 auto_fetch_en    : 1;
    uint32 auto_mode_en     : 1;
    uint32 direct_io        : 1;
    uint32 channel_id       : 8;
    uint32 func_type        : 5;
    uint32 weight           : 4;
    uint32 rsv0              : 2;

    uint32 current_index;
    uint32 desc_num;                                       /**< init desc number for channel */
    uint32 desc_depth;
    uint32 data_num;
    uintptr mem_base;

    uint32 data_size;                                        /**< data size per desc, used for alloc memory */
    uint32 cfg_size;                                          /**< desc cfg size used for config desc, for packet/reg uint is Byte , for InfoDma uint is Entry */

    sys_dma_desc_t* p_desc;                               /**< descriptors used by packet(TX) DMA */
    sys_dma_tx_check_t* p_desc_check;                                     /**< indicate desc is used ot not , used for packet tx>*/

    sal_mutex_t* p_mutex;    /**< channel mutex  */
    sys_dma_desc_info_t* p_desc_info;
    sys_dma_tx_mem_t* p_tx_mem_info;
    sal_fifo_t* p_data_fifo;
    uint16 threshold;
    uint8 cb_type;
    uint8 tx_crc_len;
};
typedef struct sys_dma_chan_s sys_dma_chan_t;

struct sys_dma_timer_session_s
{
    uintptr phy_addr;     /*session data address */
    uint32  desc_idx;     /*session used desc index*/
    uint8   state;        /*0: diable tx, 1: enable tx */
    uint8   rsv[3];
};
typedef struct sys_dma_timer_session_s sys_dma_timer_session_t;

struct sys_dma_thread_s
{
    char desc[64];
    sal_sem_t* p_sync_sem;
    sal_task_t* p_sync_task;
    uint8 chan_id[8];
    uint8 chan_num;
    uint8 lchip;
    uint16 prio;
};
typedef struct sys_dma_thread_s sys_dma_thread_t;

struct sys_dma_master_s
{
    sys_dma_chan_t dma_chan_info[32];
    sys_dma_stats_t dma_stats[12];
    uint16 dma_thread_pri[32];
    uint16 packet_rx_chan_num;
    ctc_vector_t* p_thread_vector; /* store sync thread info */

    DMA_CB_FUN_P dma_cb[SYS_DMA_CB_MAX_TYPE];
    CTC_PKT_RX_CALLBACK dma_rx_cb;
    DMA_DUMP_FUN_P dma_dump_cb;

    uint32      dma_en_flag;                /**< flag indate which dma channel is enable, ont bit present one channel */
    uint32 dma_high_addr;

    uint32  hw_learning_sync:1;
    uint32  dma_stats_en:1;
    uint32  wb_reloading:1;
    uint32  wb_keep_knet:1;
    uint32  flow_stats_sync_mode:1; /* global and acl stats sync mode, 0 :fifo sync, 1 :dma sync*/
    uint32  op_bmp      :12;
    uint32  rsv         :15;

    sal_spinlock_t* p_tx_mutex;
    sal_spinlock_t* p_list_lock;
    sal_fifo_t* pkt_thread_fifo;

    uint16  pkt_tx_timer_en:1;
    uint16  init:1;
    uint16  intr_chan_num:6;/* the number of dma channels that enable and interrupt enable */
    uint16  core_pp_base:8;/**< for Arctic, store core pp base per core*/
    uint16  tx_timer;

    uint8 intr_chan_array[32];/* array of DMA channel ID which enable interrupt */
    uint16 chan_type[32];/**< chan type, e.g. DRV_DMA_PACKET_RX0_CHAN_ID, refer to drv_constant_t */
    sys_dma_timer_session_t  tx_session[SYS_PKT_MAX_TX_SESSION];

    ctc_dma_global_cfg_t dma_global_cfg;
    uint32* p_nonuc_bmask_dma;
    uint64 phy_base;
    void* p_virt_base;
    uint8 dma_cb_in_cnt[32];
    uint8 dma_cb_out_cnt[32];
};
typedef struct sys_dma_master_s sys_dma_master_t;

extern sys_dma_master_t* p_usw_dma_master[CTC_MAX_LOCAL_CHIP_NUM_PP];

/***************************************************************
 *
 *  Functions
 *
 ***************************************************************/

#ifdef __cplusplus
}
#endif

#endif

